﻿// This file is part of VideoLan.Inteop
//
// Copyright (C) 2008, Michael Melendez, http://www.MeediOS.com
//
//VideoLan.Inteop is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either 
//version 2.1 of the License, or (at your option) any later version.
//
//VideoLan.Inteop is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public 
//License along with this library.  If not, see <http://www.gnu.org/licenses/>.


using System;
using System.Collections.Generic;
using System.Text;

namespace VideoLan
{
    public class VlcLog : IDisposable, IEnumerable<VlcLogMessage>
    {
        #region Private Members

        /// <summary>
        /// COM pointer to a vlc exception.  We will only use 1 exception pointer, 
        /// so we must always clear it out after use
        /// </summary>
        private libvlc_exception_t p_exception;

        /// <summary>
        /// COM pointer to our vlc media instance
        /// </summary>
        internal IntPtr p_log;

        #endregion

        #region Properties

        public uint Count
        {
            get
            {
                uint rtn = InteropMethods.libvlc_log_count(p_log, ref p_exception);
                p_exception.CheckException();
                return rtn;
            }
        }

        #endregion

        #region Constructors/Destructors


        internal VlcLog(IntPtr p_log)
        {
            this.p_log = p_log;
        }

        ~VlcLog()
        {
            Dispose(false);
        }
        #endregion

        #region Methods

        #region VlcLog Methods

        public void Clear()
        {
            InteropMethods.libvlc_log_clear(p_log, ref p_exception);
            p_exception.CheckException();
        }

        #endregion

        #region IDisposable Methods

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected void Dispose(bool disposing)
        {
            // release managed code
            if (disposing)  
            {

            }

            //release unmanaged code
            if (p_log != IntPtr.Zero)
            {
                InteropMethods.libvlc_log_close(p_log, ref p_exception);
                p_exception.CheckException();
            }
            p_log = IntPtr.Zero;
        }

        #endregion

        #region IEnumerable<VlcLogMessage> Methods

        public IEnumerator<VlcLogMessage> GetEnumerator()
        {
            return new VlcLogEnumerator(this);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new VlcLogEnumerator(this);
        }

        #region Custom Enumerator

        private class VlcLogEnumerator : IDisposable, IEnumerator<VlcLogMessage>
        {

            #region Private Members

            private VlcLog _log;
            private VlcLogMessage _cur_msg;
            /// <summary>
            /// COM pointer to our vlc media instance
            /// </summary>
            internal IntPtr p_log_iter;

            #endregion

            #region Properties

            public object Current
            {
                get
                {
                    return _cur_msg;
                }
            }

            VlcLogMessage IEnumerator<VlcLogMessage>.Current
            {
                get { return _cur_msg; }
            }

            #endregion

            #region Constructors/Destructors

            public VlcLogEnumerator(VlcLog log)
            {
                _log = log;
                Initalize();
            }

            ~VlcLogEnumerator()
            {
                Dispose(false);
            }

            private void Initalize()
            {
                //Get the message iterator
                p_log_iter = InteropMethods.libvlc_log_get_iterator(_log.p_log, ref _log.p_exception);
                _log.p_exception.CheckException();

                //Allocate the first message
                MoveNext();
            }
            #endregion

            #region IDisposable Members

            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }

            protected void Dispose(bool disposing)
            {
                // release managed code
                if (disposing)
                {

                }

                //release unmanaged code
                if (p_log_iter != IntPtr.Zero)
                {
                    InteropMethods.libvlc_log_iterator_free(p_log_iter, ref _log.p_exception);
                    _log.p_exception.CheckException();
                }
                p_log_iter = IntPtr.Zero;
            }
            #endregion

            #region IEnumerator<VlcLogMessage> Members
            public void Reset()
            {
                Dispose(false);
                _cur_msg = null;
                Initalize();
            }
            public bool MoveNext()
            {
                bool rtn = InteropMethods.libvlc_log_iterator_has_next(p_log_iter, ref _log.p_exception);
                _log.p_exception.CheckException(); 
                
                if (rtn)
                {                    
                    _cur_msg = new VlcLogMessage();
                    InteropMethods.libvlc_log_iterator_next(p_log_iter, ref _cur_msg.msg, ref _log.p_exception);
                    _log.p_exception.CheckException();
                }
                return rtn;
            }
            #endregion
        }
        #endregion

        #endregion

        #endregion
    }

    public class VlcLogMessage
    {
        internal libvlc_log_message msg;

        public uint Size
        {
            get { return msg.sizeof_msg; }
        }
        public int Severity
        {
            get { return msg.i_severity; }
        }
        public string Header
        {
            get { return msg.psz_header; }
        }
        public string Name
        {
            get { return msg.psz_name; }
        }
        public string Type
        {
            get { return msg.psz_type; }
        }
        public string Message
        {
            get { return msg.psz_message; }
        }

        internal VlcLogMessage()
        {
            msg = new libvlc_log_message();
        }
    }
}
